Skip to content

[Repo Assist] Use Popover API for code snippet tooltips; fix scroll-offset positioning#1061

Merged
nojaf merged 14 commits intomainfrom
repo-assist/improve-popover-tooltips-804beaa-613ba4f90485b3ec
Mar 10, 2026
Merged

[Repo Assist] Use Popover API for code snippet tooltips; fix scroll-offset positioning#1061
nojaf merged 14 commits intomainfrom
repo-assist/improve-popover-tooltips-804beaa-613ba4f90485b3ec

Conversation

@github-actions
Copy link
Copy Markdown
Contributor

@github-actions github-actions bot commented Mar 2, 2026

🤖 This PR was created by Repo Assist, an automated AI assistant.

Closes #422

Summary

Migrates hover tooltips (the div.fsdocs-tip elements shown when hovering over syntax tokens in code blocks) to use the browser-native [Popover API]((developer.mozilla.org/redacted), with a clean fallback for older browsers.

Changes

src/FSharp.Formatting.CodeFormat/HtmlFormatting.fs

Add the popover attribute to every generated div.fsdocs-tip element:

(div class="fsdocs-tip" id="fstips3")...(/div)

(div popover class="fsdocs-tip" id="fstips3")...(/div)

docs/content/fsdocs-tips.js

  • Popover API path (modern browsers, Baseline 2024): set position: fixed, then call el.showPopover() / el.hidePopover(). Elements in the top layer are always rendered above all other page content — no z-index arithmetic needed.
  • Fallback path (older browsers): retain existing position: absolute + display: block/none behaviour unchanged.
  • Bug fix: the right-edge overflow correction used y instead of x as the base for the left-shift; corrected to x.
  • Bug fix: currentTipElement was never cleared on hide; now set to null together with currentTip.

docs/content/fsdocs-default.css

Add div.fsdocs-tip:popover-open { display: block; } so the author-level display: none rule does not suppress the Popover API reveal (author rules take precedence over UA rules in the cascade). Also add margin: 0 to prevent UA default popover margins from shifting the tooltip.

Why the Popover API?

Property Old (JS absolute positioning) New (Popover API)
Rendering layer Normal stacking context — needs z-index: 1000 Browser top layer — always above everything
Positioning on scroll Bug: clientX/Y used with position: absolute → offset when scrolled Correct: clientX/Y used with position: fixed in top layer
Keyboard dismiss Manual document.onkeydown handler Built-in Escape key handling for auto popovers
Browser support All [Baseline 2024]((developer.mozilla.org/redacted) (Chrome 114+, Firefox 125+, Safari 17+)

Test Status

  • ✅ Build: dotnet build src/FSharp.Formatting.CodeFormat/ — 0 warnings, 0 errors
  • ✅ Tests: dotnet test tests/FSharp.CodeFormat.Tests/ — 20 passed, 2 skipped (pre-existing infrastructure skips)
  • ✅ Formatting: Fantomas check on changed .fs file — no changes needed
  • ⚠️ Visual verification: manual testing of hover tooltips, light-dismiss (Escape), and scroll-position accuracy recommended before merge

Generated by Repo Assist for issue #422

Generated by Repo Assist

To install this agentic workflow, run

gh aw add githubnext/agentics/workflows/repo-assist.md@da02dddebe71d9a937665abdcd1f5214dab852a7

- Add `popover` attribute to `div.fsdocs-tip` elements in HtmlFormatting.fs,
  placing them in the browser top layer when supported (Baseline 2024).
- Update fsdocs-tips.js to call showPopover()/hidePopover() on browsers that
  support the Popover API; fall back to display:block/none on older browsers.
- Switch to `position: fixed` in the Popover API path (correct for top-layer
  elements) and fix a scroll-offset bug where tooltips appeared at wrong
  positions when the page was scrolled.
- Fix a minor bug in the right-edge overflow correction (was using `y` instead
  of `x` as the base for the left-shift calculation).
- Add `div.fsdocs-tip:popover-open { display: block }` to fsdocs-default.css
  so author-level display:none does not suppress the Popover API reveal.
- Update RELEASE_NOTES.md.

Closes #422

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@dsyme dsyme marked this pull request as ready for review March 6, 2026 23:59
@nojaf
Copy link
Copy Markdown
Collaborator

nojaf commented Mar 9, 2026

/repo-assist there is a regression here. When using the popover api, I see a black background on the surrounding tooltip area.
image

I also wonder if we need to stay backwards compatible here? Giving our technical audience the popover api will be present in high numbers. I don't think it is worth having the two mechanisms.

Also, improve to popup to have a very subtle fade in animation.

…fade-in

- CSS: add `inset: unset` to `div.fsdocs-tip:popover-open` to reset the UA
  popover stylesheet's `inset: 0` (i.e. right:0 / bottom:0), which was
  stretching the element across the viewport and causing the visible dark area
  around the tooltip.
- CSS: add `position: fixed` explicitly in the :popover-open rule so the
  element is correctly anchored to the JS-supplied left/top coordinates.
- CSS: add a 120ms ease-out opacity fade-in animation for a subtle reveal.
- JS: remove the display-toggle fallback branch entirely. The Popover API is
  Baseline 2024 (Chrome 114+, Firefox 125+, Safari 17+) and the technical
  audience of fsdocs users will have modern browsers.
- RELEASE_NOTES: update entry to reflect the simplified (no-fallback) design
  and the animation addition.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions
Copy link
Copy Markdown
Contributor Author

github-actions bot commented Mar 9, 2026

Commit pushed: 95f9b91

Generated by Repo Assist

@github-actions

This comment has been minimized.

@nojaf
Copy link
Copy Markdown
Collaborator

nojaf commented Mar 9, 2026

/repo-assist the black background is not fixed for me in latest Chrome.

I also wonder if we still need the more archaic code generated in

<span onmouseout="hideTip(event, 'fs1', 1)" onmouseover="showTip(event, 'fs1', 1)" class="fn">helloWorld</span>

onmouseout and onmouseover to trigger popover feels like fighting the modern api.
Is there no better way to do this? Modify the generated html if you must.

…ion; fix Chrome popover background

- HtmlFormatting.fs: emit data-fsdocs-tip / data-fsdocs-tip-unique instead
  of inline onmouseover/onmouseout handlers; overlapping vs non-overlapping
  cases now produce identical output (owner param is no longer needed)
- GenerateHtml.fs (ApiDocs): same data-* attrs on code elements; add the
  popover attribute to fsdocs-tip divs so showPopover() works there too
- fsdocs-tips.js: add delegated mouseover/mouseout listeners that read
  data-fsdocs-tip attributes; wrap showPopover() in try/catch for safety;
  keep showTip/hideTip on window for backward-compat with cached docs
- fsdocs-default.css: add explicit background-color inside :popover-open
  to override Chrome UA top-layer canvas default (fixes black background);
  add [data-fsdocs-tip] cursor rule alongside legacy span[onmouseout]

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions
Copy link
Copy Markdown
Contributor Author

github-actions bot commented Mar 9, 2026

Commit pushed: c4f034a

Generated by Repo Assist

@github-actions

This comment has been minimized.

@nojaf nojaf requested a review from dsyme March 9, 2026 09:48
@dsyme
Copy link
Copy Markdown
Contributor

dsyme commented Mar 9, 2026

@nojaf Good work.

@nojaf
Copy link
Copy Markdown
Collaborator

nojaf commented Mar 10, 2026

/repo-assist why is CI failing here?

…vention

The ConvertCommand test checked that 'fsdocs-tip' is not in the output
when no template is given. Since the span elements now use data-fsdocs-tip
attributes (instead of onmouseover/onmouseout inline handlers), the output
always contains 'fsdocs-tip' as part of the attribute name.

The test intent is to verify that tooltip *div* elements (class="fsdocs-tip")
are not emitted without a template. Update the assertion to check for
class="fsdocs-tip" specifically, which only matches the tooltip divs.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions
Copy link
Copy Markdown
Contributor Author

Commit pushed: b79613e

Generated by Repo Assist

@github-actions
Copy link
Copy Markdown
Contributor Author

🤖 Repo Assist here — found and fixed the CI failure.

Root cause

The failing test was ConvertCommand omits fsdocs-tip divs when no template given in fsdocs-tool.Tests.

All tests passed (87/87), but the fsdocs-tool.Tests suite had 1 failure that appeared earlier in the CI log. The test asserted:

html |> shouldNotContainText "fsdocs-tip"

This was originally written to verify that tooltip (div class="fsdocs-tip") elements are not emitted when no template is provided. However, since this PR changed <span onmouseover=...> to <span data-fsdocs-tip="..." ...>, the generated HTML now always contains "fsdocs-tip" as part of the data attribute names — causing the assertion to fail even though no tooltip divs are being emitted.

Fix

Updated the assertion to be specific about what it's testing — the absence of tooltip div elements:

// Before
html |> shouldNotContainText "fsdocs-tip"

// After
html |> shouldNotContainText "class=\"fsdocs-tip\""

Committed and pushed. All 8 fsdocs-tool.Tests now pass.

Generated by Repo Assist for issue #1061 ·

To install this agentic workflow, run

gh aw add githubnext/agentics/workflows/repo-assist.md@346204513ecfa08b81566450d7d599556807389f

@nojaf nojaf merged commit a7b9e55 into main Mar 10, 2026
4 checks passed
@nojaf nojaf deleted the repo-assist/improve-popover-tooltips-804beaa-613ba4f90485b3ec branch March 10, 2026 13:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

CSS tooltips as an alternative (or replacement) for JS tooltips

2 participants